/*
	This plugin replace all your input having a specified class ( i.e. class='bit' )
	with a simple and personalizable switch slider.
	You can continue to use the input field in your form and it will return values:
	- "1" when the left side is selected
	- "0" when the right side is selected
	or the [values] parameters you set.
	Parameters:
	- labels : label names separed by a |.  'labels' are 'on|off' by default
	- values : field values separed by a |.  'labels' are '1|0' by default
	- animate : animate transiction between values. 'animate' is true  by default
	- cssDefault : apply a style similar to the inupt fields
	- hideInput : hide the input field replaced, is true by default
	Returns:
	- the newly created switch element <span class='onoff'>...</span>
	
	Author Fulvio Baratta
	
	Sample code
	var switches = $('.bit').switchify({'labels':'true|false','animate':false});
*/
(function( $ ){
	$.fn.switchify = function( options ) {
		
		var settings = {
			'labels' : 'on|off',
			'values' : '1|0',
			'animate' : true,
			'cssDefault' : true,
			'hideInput' : true,
			'onCallback' : false,
			'offCallback' :false
		};

		if ( options ) { 
			$.extend( settings, options );
		}
		
		var lbls = settings.labels.split('|'); // label values
		var values = settings.values.split('|'); // field returned values
		var onValue = values[0];
		var offValue = values[1];

		/* prepare span elements */
		var onoffString = "<span class='onoff'><span class='on'>";
			onoffString += lbls[0];
			onoffString += "</span><span class='off'>";
			onoffString += lbls[1];
			onoffString += "</span><span class='onoffcover'></span></span>";
		
		if ( settings.hideInput )
			this.hide(); // hide all input element
		this.after( onoffString ); // append onoff element to all elements
		
		/* minimal css style for switch */
		this.next('.onoff').css({
			'cursor':'default'
		});
		this.next('.onoff').children('span').css({
			'textAlign':'center',
			'padding':'1px 3px'
		});
		this.next('.onoff').children('.onoffcover').css({
			'position':'absolute',
			'cursor':'pointer'
		});
		
		/* default css applied, similar to a standard input field */
		if ( settings.cssDefault ) {
			this.next('.onoff').css({
				'borderTop':'2px solid #404040',
				'borderLeft':'2px solid #404040',
				'borderBottom':'1px solid #d4d0c8',
				'borderRight':'1px solid #d4d0c8',
				'fontFamily':$('input').css('fontFamily'),
				'fontSize':$('input').css('fontSize'),
				'color':$('input').css('color'),
				'backgroundColor':$('input').css('backgroundColor')
			});
			this.next('.onoff').children('.onoffcover').css({
				'opacity':'.7',
				'backgroundColor':'#404040'
			});
		}
		
		this.each(function() {
			var bit = $(this); // .bit input element
			var onoff, on, off, onoffcover; // span elements
			var wOn, wOff, wOnoffcover; // on, off and onoffcover span width
			var padding; // extra padding to be added to match width between labels length
			var marginLeft;
			
			/* initialize span elements */
			onoff = bit.next( '.onoff' );
			on = onoff.children( '.on' );
			off = onoff.children( '.off' );
			onoffcover = onoff.children( '.onoffcover' );
			
			/* fix labels length differences, adding extra padding to smaller label */
			wOn = on.width();
			wOff = off.width();
			if ( wOn > wOff ) {
				padding = Math.floor( (on.innerWidth() - wOff) / 2 );
				off.css( {'padding-left':padding+'px','padding-right':padding+'px'} );
				wOnoffcover = on.width();
			}
			else if ( wOff > wOn ) {
				padding = Math.floor( (off.innerWidth() - wOn) / 2 );
				on.css( {'padding-left':padding+'px','padding-right':padding+'px'} );
				wOnoffcover = off.width();
			}
			else {
				wOnoffcover = on.width();
			}
			wOnoffcover ++;
			onoffcover.width( wOnoffcover );

			/* adjust cover height and positioning */
			onoffcover.height( onoff.height() );
			onoffcover.css( 'top', onoff.position().top );
			onoffcover.css( 'left', onoff.position().left );
			marginLeft = onoffcover.innerWidth();

			/* set cover position when no .bit default specified */
			if ( bit.val() == onValue ) {
				onoffcover.css( 'marginLeft', marginLeft + 'px' );
				if(settings.onCallback) {
					settings.onCallback();
				}
			}
			else if ( bit.val() == offValue ) {
				onoffcover.css( 'marginLeft', '0px' );
			}
			else {
				onoffcover.css( 'marginLeft', '0px' );
				bit.val( offValue );
			}

			/* click event on onoffcover element */
			onoffcover.click( function(){
				if ( $(this).css('marginLeft') == '0px' ) {
					if ( !settings.animate ) 
						$(this).css( {'marginLeft':marginLeft} );
					else
						$(this).animate( {'marginLeft':marginLeft} );
					bit.val( onValue );
					if(settings.onCallback) settings.onCallback();
					
				}
				else {
					if ( !settings.animate ) 
						$(this).css( {'marginLeft':'0px'} );
					else
						$(this).animate( {'marginLeft':'0px'} );
					bit.val( offValue );
					if(settings.offCallback) settings.offCallback();
				}
			});
		
		});
		
		return this.next('.onoff');
		
	};
})( jQuery );